use axum::{
    extract::State,
    http::{HeaderMap, StatusCode},
    response::Json,
};
use base64::{engine::general_purpose::URL_SAFE, Engine as _};
use hmac::{Hmac, Mac};
use serde::{Deserialize, Serialize};
use sha2::Sha256;
use std::sync::Arc;
use time::{Duration, OffsetDateTime};

#[derive(Debug, Serialize, Deserialize)]
pub struct Claims {
    pub sub: String, // 用户ID
}

#[derive(Debug, Serialize, Deserialize)]
pub struct LoginRequest {
    pub username: String,
    pub password: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct LoginResponse {
    pub token: String,
    pub expires_in: usize,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct RegisterRequest {
    pub username: String,
    pub password: String,
    pub email: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct RegisterResponse {
    pub user_id: String,
    pub message: String,
}

// 用户数据结构
#[derive(Debug, Clone)]
pub struct User {
    pub id: String,
    pub username: String,
    pub password_hash: String,
    pub email: String,
    pub created_at: OffsetDateTime,
}

// 认证服务
pub struct AuthService {
    jwt_secret: String,
}

impl AuthService {
    pub fn new(jwt_secret: String) -> Self {
        Self { jwt_secret }
    }

    // 生成JWT token
    pub fn generate_token(&self, user_id: &str) -> Result<String, String> {
        let now = OffsetDateTime::now_utc();
        let exp = now + Duration::hours(1);
        
        let header = r#"{"alg":"HS256","typ":"JWT"}"#;
        let claims = serde_json::json!({
            "sub": user_id,
            "iat": now.unix_timestamp(),
            "exp": exp.unix_timestamp()
        });
        
        let header_encoded = URL_SAFE.encode(header.as_bytes());
        let claims_encoded = URL_SAFE.encode(claims.to_string().as_bytes());
        let message = format!("{}.{}", header_encoded, claims_encoded);
        
        let mut mac = Hmac::<Sha256>::new_from_slice(self.jwt_secret.as_bytes())
            .map_err(|e| e.to_string())?;
        mac.update(message.as_bytes());
        let signature = mac.finalize().into_bytes();
        let signature_encoded = URL_SAFE.encode(signature);
        
        Ok(format!("{}.{}", message, signature_encoded))
    }

    // 验证JWT token
    pub fn verify_token(&self, token: &str) -> Result<Claims, String> {
        let parts: Vec<&str> = token.split('.').collect();
        if parts.len() != 3 {
            return Err("Invalid token format".to_string());
        }
        
        let message = format!("{}.{}", parts[0], parts[1]);
        
        // 验证签名
        let mut mac = Hmac::<Sha256>::new_from_slice(self.jwt_secret.as_bytes())
            .map_err(|e| e.to_string())?;
        mac.update(message.as_bytes());
        let expected_signature = mac.finalize().into_bytes();
        let provided_signature = URL_SAFE.decode(parts[2])
            .map_err(|e| format!("Invalid signature: {}", e))?;
        
        if expected_signature.as_slice() != provided_signature.as_slice() {
            return Err("Invalid signature".to_string());
        }
        
        // 验证过期时间
        let claims_bytes = URL_SAFE.decode(parts[1])
            .map_err(|e| format!("Invalid claims: {}", e))?;
        let claims_str = String::from_utf8(claims_bytes)
            .map_err(|e| format!("Invalid UTF-8: {}", e))?;
        let claims_value: serde_json::Value = serde_json::from_str(&claims_str)
            .map_err(|e| format!("Invalid JSON: {}", e))?;
        
        let exp = claims_value["exp"].as_i64()
            .ok_or("Missing expiration time")?;
        let now = OffsetDateTime::now_utc().unix_timestamp();
        
        if exp < now {
            return Err("Token expired".to_string());
        }
        
        let sub = claims_value["sub"].as_str()
            .ok_or("Missing subject")?;
        
        Ok(Claims {
            sub: sub.to_string(),
        })
    }

    // 密码哈希（简化版，实际应该使用bcrypt等安全哈希）
    pub fn hash_password(&self, password: &str) -> String {
        // 实际项目中应该使用bcrypt::hash等安全方法
        format!("hashed_{}", password) // 简化实现
    }

    // 验证密码
    pub fn verify_password(&self, password: &str, hash: &str) -> bool {
        // 实际项目中应该使用bcrypt::verify等安全方法
        hash == format!("hashed_{}", password) // 简化实现
    }
}

// 从请求头提取token
pub fn extract_token(headers: &HeaderMap) -> Option<String> {
    headers
        .get("Authorization")
        .and_then(|value| value.to_str().ok())
        .and_then(|auth_header| {
            if auth_header.starts_with("Bearer ") {
                Some(auth_header[7..].to_string())
            } else {
                None
            }
        })
}

// 登录处理函数
pub async fn login(
    State(state): State<Arc<crate::handlers::AppState>>,
    Json(payload): Json<LoginRequest>,
) -> Result<Json<LoginResponse>, StatusCode> {
    // 简化验证 - 实际应该查询数据库
    if payload.username == "admin" && payload.password == "password" {
        let token = state.auth_service
            .generate_token("user_123")
            .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
        
        Ok(Json(LoginResponse {
            token,
            expires_in: 3600, // 1小时
        }))
    } else {
        Err(StatusCode::UNAUTHORIZED)
    }
}

// 注册处理函数
pub async fn register(
    State(state): State<Arc<crate::handlers::AppState>>,
    Json(payload): Json<RegisterRequest>,
) -> Result<Json<RegisterResponse>, StatusCode> {
    // 简化实现 - 实际应该保存到数据库
    let _password_hash = state.auth_service.hash_password(&payload.password);
    
    // 模拟用户创建
    let user_id = format!("user_{}", OffsetDateTime::now_utc().unix_timestamp());
    
    Ok(Json(RegisterResponse {
        user_id,
        message: "注册成功".to_string(),
    }))
}